package home

import (
	"fmt"
	"math"
	"strconv"
)

// const byte_len_64 = 20 // 数字串长，也是循环数

const mask_64_0 = uint64(0o_1111_1111_1111_1111_1111) //0b_001_001_001_001_001_001_001_001_001
const mask_64_1 = uint64(mask_0 << 1)
const mask_64_2 = uint64(mask_1 << 1)

const hexs_len = 6

var hexs_64 = [hexs_len]uint64{0, 1, 3, 4, 5, 7}

func S1N(p, n uint64) uint64 {
	b2 := (p & mask_64_2) >> 2
	b1 := (n & mask_64_1) >> 1
	b0 := n & mask_64_0
	return ((b2 ^ b1 ^ b0) << 2) | ((b2 & b0) << 1) | (b2 | b1)
}

type lv_fun struct {
	fn  func(args ...uint64) uint64
	str string
}

const lv_len = 6

var lv_funcs = make([]lv_fun, 0)

func init_lv_funcs() {
	const lv = lv_len - 1
	const b = 2 //begin
	lv_funcs = append(lv_funcs, lv_fun{str: "(0,1)", fn: func(args ...uint64) uint64 { return S1N(args[0], args[1]) }})
	lv_funcs = append(lv_funcs, lv_fun{str: "(1,0)", fn: func(args ...uint64) uint64 { return S1N(args[1], args[0]) }})

	for i := b; i < lv+b; i++ {
		for _, lf := range lv_funcs {
			// GO特有的闭包问题
			i2, f := i, lf.fn

			lv_funcs = append(lv_funcs, lv_fun{
				str: "(" + lf.str + "," + strconv.Itoa(i2) + ")",
				fn:  func(args ...uint64) uint64 { return S1N(args[0], f(args[1:]...)) },
			})
			lv_funcs = append(lv_funcs, lv_fun{
				str: "(" + strconv.Itoa(i2) + "," + lf.str + ")",
				fn:  func(args ...uint64) uint64 { return S1N(f(args[1:]...), args[0]) },
			})
		}
	}
}

func init_hex_slc(w int) []uint64 {
	rtn := make([]uint64, int(math.Pow(6, float64(w))))
	cnt := 0
	var tmp uint64
	ForW(w, 0, 5)(func(args ...interface{}) {
		tmp = 0
		for i := 0; i < len(args); i++ {
			tmp = (tmp << 3) | hexs_64[args[i].(int)]
		}
		rtn[cnt] = tmp
		cnt++
	})

	return rtn
}

func sym_len1_lv6(hexs []uint64) {
	fmt.Println("hexs:", hexs)

	const w = lv_len

	// init_lv_funcs()

	var ints [w + 1]uint64

	// 当 len(hexs) == 64 , w==6 时，根本跑不完 64^6 这么多次大循环
	// 小循环最坏情况是 64^2
	ForW(w, 0, len(hexs)-1)(func(args ...interface{}) {
		for i, v := range args {
			ints[i+1] = hexs[v.(int)]
		}

		for _, v := range lv_funcs {
			// fmt.Println(v.str, ints)
			f := true
			for i := 0; i < len(hexs); i++ {
				ints[0] = hexs[i]
				if ints[0] != v.fn(ints[:]...) {
					f = false
					break
				}

				// else {
				// 	 fmt.Println(i, v.str, ints)
				// }
			}

			if f {
				fmt.Println("Pairs", v.str, ints)
			}
		}

	})
}
